package cn.com.b2office.dao.hibernate;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.Order;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import cn.com.b2office.bean.ItemQueryParam;
import cn.com.b2office.cache.ItemCache;
import cn.com.b2office.dao.ItemDao;
import cn.com.b2office.domain.Item;

/**
 * 
 * @author wangtao.upc@gmail.com
 * 
 */
public class ItemDaoHibernateImpl extends HibernateDaoSupport implements
		ItemDao {

	private ItemCache itemCache = ItemCache.getInstance();

	public String createItem(Item item) {
		return (String) getHibernateTemplate().save(item);
	}

	public Item getItem(String itemId) {
		return (Item) getHibernateTemplate().get(Item.class, itemId);
	}

	public List<Item> queryItems(ItemQueryParam param) {
		List<Item> list = null;

		list = itemCache.get(param.getCategoryId(), param.getBrandId(), param
				.getSortFactor(), String.valueOf(param.getSortSeq()));
		if (list == null) {

			Session s = getSession();
			try {
				Criteria criteria = s.createCriteria(Item.class);
				criteria.add(Expression.eq("published", 1));
				if (param.getCategoryId() != null)
					criteria.add(Expression.like("item_clsno", param
							.getCategoryId()
							+ "%"));
				if (param.getBrandId() != null)
					criteria.add(Expression.like("item_brand", param
							.getBrandId()
							+ "%"));
				// 排序
				if (param.getSortFactor() != null) {
					if (param.getSortSeq() == 1) {
						if (param.getSortFactor().equalsIgnoreCase("price"))
							criteria.addOrder(Order.desc("b2hprice"));

					} else if (param.getSortSeq() == 0) {
						if (param.getSortFactor().equalsIgnoreCase("price"))
							criteria.addOrder(Order.asc("b2hprice"));
					}

				}

				criteria.addOrder(Order.desc("defaultSort"));

				// criteria.setFirstResult(param.getFirstResult());
				// criteria.setMaxResults(param.getPageSize());
				// 启用查询缓存
				criteria.setCacheable(true);
				list = criteria.list();
			} catch (RuntimeException e) {
				throw e;
			} finally {
				releaseSession(s);
			}

			itemCache.put(param.getCategoryId(), param.getBrandId(), param
					.getSortFactor(), String.valueOf(param.getSortSeq()), list);
		}

		int totalSize = list.size();
		if (param.getFirstResult() > totalSize)
			return null;
		if ((param.getFirstResult() + param.getPageSize()) < totalSize)
			return subList(list, param.getFirstResult(), param.getFirstResult()
					+ param.getPageSize());
		else
			return subList(list, param.getFirstResult(), totalSize);
	}

	private List<Item> subList(List<Item> list, int fromIndex, int endIndex) {
		return list.subList(fromIndex, endIndex);
	}

	public void removeItem(String itemId) {
		Item item = (Item) getHibernateTemplate().get(Item.class, itemId);
		if (item != null)
			getHibernateTemplate().delete(item);
	}

	public void removeItem(Item item) {
		getHibernateTemplate().delete(item);
	}

	public void updateItem(Item item) {
		getHibernateTemplate().update(item);

	}

	public List<Item> findSpecialItems(List<String> itemIdList) {
		List<Item> items = null;
		Session s = getSession();
		try {
			Criteria criteria = s.createCriteria(Item.class);
			criteria.add(Expression.in("item_no", itemIdList));
			// 缓存查询
			criteria.setCacheable(true);
			items = criteria.list();
		} catch (RuntimeException e) {
			e.printStackTrace();
		} finally {
			releaseSession(s);
		}
		return items;
	}

	public List<Item> findItemsByBrand(String brandId) {
		List<Item> items = null;
		Session s = getSession();
		try {
			Query query = s.createQuery(
					"from Item where published=1 and item_brand=:brandId")
					.setString("brandId", brandId);
			// 缓存查询
			query.setCacheable(true);
			items = query.list();
		} catch (RuntimeException e) {
			e.printStackTrace();
		} finally {
			releaseSession(s);
		}
		return items;
	}

	public List<Item> findItemsByCategory(String categoryId) {
		List<Item> items = null;
		Session s = getSession();
		try {
			Criteria criteria = s.createCriteria(Item.class);
			criteria.add(Expression.eq("published", 1));
			criteria.add(Expression.like("item_clsno", categoryId + "%"));
			// 缓存查询
			criteria.setCacheable(true);
			items = criteria.list();
		} catch (RuntimeException e) {
			e.printStackTrace();
		} finally {
			releaseSession(s);
		}
		return items;
	}

	public int size(ItemQueryParam param) {
		List<Item> list = itemCache.get(param.getCategoryId(), param
				.getBrandId(), param.getSortFactor(), String.valueOf(param
				.getSortSeq()));
		if (list != null)
			return list.size();

		int size = 0;
		StringBuilder hql = new StringBuilder();
		hql.append("select count(*) from Item where published=1");
		if (param.getBrandId() != null && !param.getBrandId().trim().equals(""))
			hql.append(" and item_brand='").append(param.getBrandId()).append(
					"'");
		String categoryId = param.getCategoryId();
		if (categoryId.trim().length() == 6)
			hql.append(" and item_clsno ='").append(categoryId).append("'");
		else if (categoryId.trim().length() == 4)
			hql.append(" and item_clsno like '").append(categoryId)
					.append("%'");
		Session s = getSession();
		try {
			Query query = s.createQuery(hql.toString());
			size = ((Long) query.iterate().next()).intValue();
		} catch (RuntimeException e) {
			e.printStackTrace();
		} finally {
			releaseSession(s);
		}
		return size;
	}

	/**
	 * 通过迭代来获取Item对象，仅适合于Item对象已在缓存中的情境下,并且数据量比较小的情况下（比如最近浏览历史）
	 */
	public List<Item> findItemsByIterate(List<String> itemIdList) {
		List<Item> items = new ArrayList<Item>();
		Session s = getSession();
		try {
			for (String itemId : itemIdList) {
				Item t = (Item) s.get(Item.class, itemId);
				if (t != null)
					items.add(t);
			}
		} catch (RuntimeException e) {
			e.printStackTrace();
		} finally {
			releaseSession(s);
		}
		return items;
	}

}
